import numpy as np
import cv2
import csv
import myFFT


# 读取CSV文件并保存为二维数组
def read_csv(filename):
    data = []
    with open(filename, 'r') as file:
        reader = csv.reader(file)
        for row in reader:
            data.append([float(value) for value in row])
    return np.array(data)


# 计算二维数组的平均值和标准差
def calculate_stats(array):
    mean = np.mean(array)
    std_dev = np.std(array)
    return mean, std_dev


# 根据平均值标准差将数组映射到0-255区间
def map_to_0_255(array, mean, std_dev):
    min = mean - std_dev
    max = mean + std_dev
    print("mean - std_dev:" + str(min) + "mean + std_dev" + str(max))
    scaled_array = (array - min) / (max - min) * 255
    # np.clip()给定一个区间，区间外的值将剪裁到区间边缘。例如，如果指定了[0，1]的间隔，则小于0的值将变为0，大于1的值将变成1。
    return np.clip(scaled_array, 0, 255).astype(np.uint8)


# 根据数组最大值和最小值映射到0-255区间
def origin_to_0_255(array):
    # 将二维数组展开为一维数组
    flattened_array = [element for sublist in array for element in sublist]
    # 对展开后的数组进行排序
    sorted_array = sorted(flattened_array)
    # 计算数组长度
    array_length = len(sorted_array)
    # 计算前后子数组的索引
    front_index = int(0.001 * array_length)
    rear_index = int(0.999 * array_length)
    # 提取前后子数组
    front_subarray = sorted_array[:front_index]
    rear_subarray = sorted_array[rear_index:]
    print("frontSize" + str(len(front_subarray)) + "backSize" + str(len(rear_subarray)))
    # 取出前序子数组的最后一个元素
    min = front_subarray[-1]
    # 取出后序子数组的最后一个元素
    max = rear_subarray[0]
    print("afterProcessMin:" + str(min) + "afterProcessMax" + str(max))
    origin_array = (array - min) / (max - min) * 255
    # np.clip()给定一个区间，区间外的值将剪裁到区间边缘。例如，如果指定了[0，1]的间隔，则小于0的值将变为0，大于1的值将变成1。
    return np.clip(origin_array, 0, 255).astype(np.uint8)

def Open_Frame_IRV(inpath, frame, width, hight):
    f = open(inpath, "rb")  # rb：也即 binary mode，read()操作返回的是bytes
    # frame  = 10   #irv：32*1024 视频的头，(640*480*2+1024) 一帧的长度
    f.seek(32 * 1024 + (frame - 1) * (hight * width * 2 + 1024), 0)  # 第一个代表需要移动偏移的字节数,0 代表从文件开头开始算起
    ccc = f.read(hight * width * 2)  # python在读取文件的时候是根据光标位置来读取的。读一行以后光标位置到了下一行。再来个read又到了下一行。
    img = np.frombuffer(ccc,
                        dtype='uint16')  # read的数值以bytes的类型保存，通过np.frombuffer方法还原成类型为uint16的ndarray，这种方式还原出来的ndarray
    # 是只读的。
    img = img.reshape((hight, width))
    # img=img[:-2,:-2] #去边缘黑边
    # img = np.squeeze(img)
    f.close()
    return img

# 读取视频总帧数
def Read_TotalFrame_IRV(inpath, w, h):
    f = open(inpath, "rb")  # rb：也即 binary mode，read()操作返回的是bytes
    f.seek(0, 2)
    size = f.tell()
    Total_num = int((size - 32 * 1024) / (w * h * 2 + 1024)) - 1
    return Total_num

# 根据csv查找坏点
def findBadPointByCsv(k):
    # 读取CSV文件
    filename = 'tempPhase.csv'  # 替换为你的CSV文件路径
    data_array = read_csv(filename)

    print("原始相位数据最小值:", np.min(data_array), "原始相位数据最大值", np.max(data_array))

    # 计算平均值和标准差
    mean, std_dev = calculate_stats(data_array)
    print("相位平均值：", mean, "相位标准差", std_dev)
    # 获取图像的高度和宽度
    height, width = data_array.shape

    # 存储像素点坐标的数组
    out_of_range_pixels = []

    # 遍历每个像素点
    for y in range(height):
        for x in range(width):
            pixel_value = data_array[y, x]
            if pixel_value < mean - k * std_dev or pixel_value > mean + k * std_dev:
                out_of_range_pixels.append((y, x))
    print("坏点数量：", len(out_of_range_pixels))
    print("坏点坐标：", out_of_range_pixels)


# 读取IRV并计算得到对应的相位图保存到Csv表格中 irvpath视频路径 视频起始帧 视频结束帧 提取相位的频率
def IRVtoCsv(irvpath, begin, end, hz):
    # 创建列表存储对应帧数视频图像
    # 求视频的总帧数
    w = 640
    h = 480
    Total_num = Read_TotalFrame_IRV(irvpath, w, h)
    print("总帧数:", Total_num)
    lists_gray = []
    array_gray = []
    for frame in range(begin, end):
        img = Open_Frame_IRV(irvpath, frame, w, h)  # 读取红外AD值
        # 为列表赋值
        lists_gray.append(img)
    # 把lists_gray转换成np.array类型方便后续裁切 (存储的是整个视频的AD值数据)
    array_gray = np.array(lists_gray)

    # 创建输出的相位列表
    list_pha_gray = []
    for i in range(h):  # nodt为步长即下采样
        for j in range(w):
            # fft运算得到指定频率幅度值和相位值
            pha_gray = myFFT.myfft_function(array_gray[:, i, j], 0, end - begin, hz)
            # print(f'{i}行{j}列, pha:', pha_gray)
            list_pha_gray.append(pha_gray)
    # 将1行的列表重构为图像行列
    list_pha_gray_re = np.reshape(list_pha_gray, (h, w))
    # 保存数组为 CSV 文件
    np.savetxt('tempPhase.csv', list_pha_gray_re, delimiter=',')
    print("相位值计算完成，保存到tempPhase.csv中")
if __name__ == "__main__":
    irvpath = r"E:\infraVideos\20240419\3mm7s50%.IRV"
    # 读取IRV视频计算相位值并保存到tempPhase.csv中
    # IRVtoCsv(irvpath, 1, 800, 0.05)
    # 读取tempPhase.csv中的相位值进行坏点检测
    findBadPointByCsv(6)